<?php
// +----------------------------------------------------------------------
// | 百度 语音识别 语音合成
// +----------------------------------------------------------------------
// | Copyright (c) 2018-2020 wmainng All rights reserved.
// +----------------------------------------------------------------------
// | Author: wmainng <wmainng@qq.com>
// +----------------------------------------------------------------------
namespace helper\baidu;

class Ai
{
    private $API_KEY;
    private $SECRET_KEY;

    /**
     * 语音识别
     * @param $file string
     * @return array
    */
    public function asr($file)
    {
        define('DEMO_CURL_VERBOSE', false); // 打印curl debug信息
        $API_KEY =  $this->API_KEY;
        $SECRET_KEY = $this->SECRET_KEY;

        $obj = ['code'=>0,'msg'=>'','data'=>''];

        # 需要识别的文件
        $AUDIO_FILE = $file;

        # 文件格式
        $FORMAT = substr($AUDIO_FILE, -3); // 文件后缀 pcm/wav/amr 格式 极速版额外支持m4a 格式

        $CUID = "123456PHP";
        # 采样率
        $RATE = 16000;  // 固定值

        # 普通版
        $ASR_URL = "http://vop.baidu.com/server_api";
        # 根据文档填写PID，选择语言及识别模型
        $DEV_PID = 1537; //  1537 表示识别普通话，使用输入法模型。1536表示识别普通话，使用搜索模型
        $SCOPE = 'audio_voice_assistant_get'; // 有此scope表示有语音识别普通版能力，没有请在网页里开通语音识别能力

        #测试自训练平台需要打开以下信息， 自训练平台模型上线后，您会看见 第二步：“”获取专属模型参数pid:8001，modelid:1234”，按照这个信息获取 dev_pid=8001，lm_id=1234
        //$DEV_PID = 8001 ;
        //$LM_ID = 1234 ;

        # 极速版需要打开以下信息 打开注释的话请填写自己申请的appkey appSecret ，并在网页中开通极速版（开通后可能会收费）
        //$ASR_URL = "http://vop.baidu.com/pro_api";
        //$DEV_PID = 80001;
        //$SCOPE = 'brain_enhanced_asr';  // 有此scope表示有极速版能力，没有请在网页里开通极速版

        $SCOPE = false; // 部分历史应用没有加入scope，设为false忽略检查

        /** 公共模块获取token开始 */
        $auth_url = "http://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=".$API_KEY."&client_secret=".$SECRET_KEY;
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $auth_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //信任任何证书
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // 检查证书中是否设置域名,0不验证
        curl_setopt($ch, CURLOPT_VERBOSE, DEMO_CURL_VERBOSE);
        $res = curl_exec($ch);
        if(curl_errno($ch))
        {
            print curl_error($ch);
        }
        curl_close($ch);

        $response = json_decode($res, true);
        if (!isset($response['access_token'])){
            $obj["msg"]="ERROR TO OBTAIN TOKEN";
            return $obj;
        }
        if (!isset($response['scope'])){
            $obj["msg"]="ERROR TO OBTAIN scopes";
            return $obj;
        }

        if ($SCOPE && !in_array($SCOPE, explode(" ", $response['scope']))){
            // 请至网页上应用内开通语音识别权限
            $obj["msg"]="CHECK SCOPE ERROR";
            return $obj;
        }
        $token = $response['access_token'];
        /** 公共模块获取token结束 */

        /** 拼接参数开始 **/
        $audio = file_get_contents($AUDIO_FILE);
        $base_data = base64_encode($audio);
        $params = array(
            "dev_pid" => $DEV_PID,
            //"lm_id" => $LM_ID,    //测试自训练平台开启此项
            "format" => $FORMAT,
            "rate" => $RATE,
            "token" => $token,
            "cuid"=> $CUID,
            "speech" => $base_data,
            "len" => strlen($audio),
            "channel" => 1,
        );

        $json_array = json_encode($params);
        $headers[] = "Content-Length: ".strlen($json_array);
        $headers[] = 'Content-Type: application/json; charset=utf-8';

        /** 拼接参数结束 **/

        /** asr 请求开始 **/

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $ASR_URL);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60); // 识别时长不超过原始音频
        curl_setopt($ch, CURLOPT_POSTFIELDS, $json_array);
        curl_setopt($ch, CURLOPT_VERBOSE, DEMO_CURL_VERBOSE);
        $res = curl_exec($ch);
        if(curl_errno($ch))
        {
            $obj["msg"]=curl_error($ch);
            return $obj;
        }
        curl_close($ch);
        /** asr 请求结束 **/

        // 打印请求参数
        $params['speech'] = 'base64_encode(file_get_contents($AUDIO_FILE))';

        // 解析结果
        $response = json_decode($res, true);
        if (isset($response['err_no']) && $response['err_no'] == 0){
            $obj["code"]=1;
            $obj["msg"]="操作成功!";
            $obj["data"]=$response['result'][0];
        }else{
            $obj["msg"]="操作失败!";
        }
        //file_put_contents("result.txt", $res);
        return $obj;
    }

    /**
     * 语音合成
     * @param $text string
     * @param $filename string
     * @return array
    */
    public function tts($text,$filename="")
    {
        define('DEMO_CURL_VERBOSE', false);
        $obj = ['code'=>0,'msg'=>'','data'=>''];
        $apiKey = $this->API_KEY;
        $secretKey = $this->SECRET_KEY;

        # 发音人选择, 基础音库：0为度小美，1为度小宇，3为度逍遥，4为度丫丫，
        # 精品音库：5为度小娇，103为度米朵，106为度博文，110为度小童，111为度小萌，默认为度小美
        $per = 103;
        #语速，取值0-15，默认为5中语速
        $spd = 5;
        #音调，取值0-15，默认为5中语调
        $pit = 5;
        #音量，取值0-9，默认为5中音量
        $vol = 5;
        // 下载的文件格式, 3：mp3(default) 4： pcm-16k 5： pcm-8k 6. wav
        $aue = 6;

        $formats = array(3 => 'mp3', 4 => 'pcm', 5 =>'pcm', 6 => 'wav');
        $format = $formats[$aue];

        $cuid = "123456PHP";//用户唯一标识

        /** 公共模块获取token开始 */
        $auth_url = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=".$apiKey."&client_secret=".$secretKey;
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $auth_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //信任任何证书
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // 检查证书中是否设置域名,0不验证
        curl_setopt($ch, CURLOPT_VERBOSE, DEMO_CURL_VERBOSE);
        $res = curl_exec($ch);
        if(curl_errno($ch))
        {
            $obj["msg"] = curl_error($ch);
            return $obj;
        }
        curl_close($ch);
        $response = json_decode($res, true);

        if (!isset($response['access_token'])){
            $obj["msg"]="ERROR TO OBTAIN TOKEN";
            return $obj;
        }
        if (!isset($response['scope'])){
            $obj["msg"]="ERROR TO OBTAIN scopes";
            return $obj;
        }
        if (!in_array('audio_tts_post',explode(" ", $response['scope']))){
            // 请至网页上应用内开通语音合成权限
            $obj["msg"]="DO NOT have tts permission";
            return $obj;
        }
        $token = $response['access_token'];
        /** 公共模块获取token结束 */

        /** 拼接参数开始 **/
        // tex=$text&lan=zh&ctp=1&cuid=$cuid&tok=$token&per=$per&spd=$spd&pit=$pit&vol=$vol
        $params = array(
            'tex' => urlencode($text), // 为避免+等特殊字符没有编码，此处需要2次urlencode。
            'per' => $per,
            'spd' => $spd,
            'pit' => $pit,
            'vol' => $vol,
            'aue' => $aue,
            'cuid' => $cuid,
            'tok' => $token,
            'lan' => 'zh', //固定参数
            'ctp' => 1, // 固定参数
        );
        $paramsStr =  http_build_query($params);
        $url = 'http://tsn.baidu.com/text2audio';
        /** 拼接参数结束 **/

        $g_has_error = false;
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt ($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $paramsStr);
        $data = curl_exec($ch);
        $res = curl_getinfo($ch);
        // 正常返回:audio/*   错误返回类型为:application/json 则转换失败
        if ($res['content_type'] == 'application/json') {
            $obj["msg"]=json_decode($data);
            return $obj;
        }
        if (curl_errno($ch)) {
            $obj["msg"]=curl_error($ch);
            return $obj;
        }
        curl_close($ch);

        //拼接文件名字
        if (!$g_has_error) {
            $filename = $filename ? $filename : strtotime(date("Y-m-dH:i:s")). rand(100000, 999999);
            $path = "upload/voice/". $filename.".".$format;
            if (file_exists($path)) {
                unlink($path);
            }
            file_put_contents($path, $data);
            $obj["code"]=1;
            $obj["msg"]="操作成功!";
            $obj["data"]=$path;
        }else{
            $file = "upload/voice/result.txt";
            file_put_contents($file, $data);
            $obj["msg"]="操作失败!";
        }
        return $obj;
    }

    /**
     * 读取音频文件时长
     * 需要使用第三方库:getID3,需要使用引用两个文件夹:getid3,helperapps
     * @throws
     * @param $voice string
     * @return integer
    */
    private function voiceTime($voice){
        //包含文件
        include_once('plugins/baidu/lib/getid3/getid3.php');
        try{
            $mp3_path=__DIR__.'/../../../public/'.$voice;
            $getID3 = new \getID3();  //实例化类
            $ThisFileInfo = $getID3->analyze($mp3_path); //分析文件，$path为音频文件的地址
            $fileDuration=$ThisFileInfo['playtime_seconds']; //这个获得的便是音频文件的时长
            $time = (int)ceil($fileDuration);
            return $time;
        }catch (\Exception $e){
            return 0;
        }
    }
}
